/*
============================================================================
 Name        : KeyLocker.cpp
 Author      : DANG Zhengfa
 Version     :
 Copyright   : Zhengfa Company Limited
 Description : CKeyLocker implementation
============================================================================
*/

#include "KeyLocker.h"
#include "Log.h"

CKeyLocker::CKeyLocker() : CActive(EPriorityStandard)	// Standard priority
{
}

void CKeyLocker::ConstructL()
{
	User::LeaveIfError(iTimer.CreateLocal());	// Initialize timer
	User::LeaveIfError(iLocker.Connect());    // Initialize keypad locker
	User::LeaveIfError(iAgent.Connect());    // Initialize system agent

	iDelaySeconds = 35; 		// default 35 seconds
	iEnableNote = ETrue;        // enable note while locking keypad
	CActiveScheduler::Add(this);	// Add to scheduler
}

CKeyLocker::~CKeyLocker()
{
	Cancel(); // Cancel any request, if outstanding
	// Delete instance variables if any
	iLocker.Close();
	iAgent.Close();
}

void CKeyLocker::DoCancel()
{
	PrintString16(_L("locker cancel"));
	iTimer.Cancel();
}

void CKeyLocker::StartL()
{
	Cancel();						// Cancel any request, just to be sure

	PrintString16(_L("CKeyLocker::StartL"));
	
	// we will check InactivityTime, if it >= iDelaySeconds, lock keypad directly
	//         otherwise, use 'Inactivity(iStatus,iDelaySeconds)' to wait event
	TBool locked = iLocker.IsKeyLockEnabled();
	if( !locked )  // if keypad isn't locked yet
	{
		TTimeIntervalSeconds seconds = User::InactivityTime();
		PrintString16(_L("User::InactivityTime is:"));
		PrintNumber(seconds.Int());
		
		if( seconds >= iDelaySeconds) // inactivity time of user is greater than our delay time, lock keypad
		{
			PrintString16(_L("Lock !!"));

			// Using the following line to enable notification or not
			iLocker.EnableSoftNotifications(ETrue);
			if(iEnableNote)
				iLocker.EnableKeyLock();
			else
				iLocker.EnableWithoutNote();
		}
	} // if( !locked ) 

	// Requests an event if the specified time interval elapses without user actvity.
	iTimer.Inactivity(iStatus,iDelaySeconds);
	SetActive();					// Tell scheduler a request is active
}

TInt CKeyLocker::RunError(TInt aError)
{
	PrintString16(_L("CKeyLocker::RunError"));
	PrintNumber(aError);
	return KErrNone;
}

void CKeyLocker::RunL()
{
	PrintString16(_L("CKeyLocker::RunL"));

	TBool locked = iLocker.IsKeyLockEnabled();
	if( locked )  // if keypad is locked already, set timer and return
	{
		PrintString16(_L("Keypad locked already"));
	}
	else  // keypad is not locked yet
	{
		if(! IsCallActive() )  // no call is ongoing
		{
			PrintString16(_L("Not locked, now to Lock!"));
			
			// Using the following line to enable notification or not
			iLocker.EnableSoftNotifications(ETrue);
			if(iEnableNote)
				iLocker.EnableKeyLock();
			else
				iLocker.EnableWithoutNote();
		}
		else  // call is going
		{
			// the following code will cause backlight to light again
			// so there is tiny problem with this solution
			PrintString16(_L("Call ongoing, ResetInactivityTime"));
			User::ResetInactivityTime();
		}
	} // locked

	iTimer.Inactivity(iStatus,iDelaySeconds);   
	SetActive();					// Tell scheduler a request is active
}

void CKeyLocker::SetTimeInterval(TInt aInterval)
{
	iDelaySeconds = aInterval;
}

void CKeyLocker::SetNote(TBool aFlag)
{
	iEnableNote = aFlag;
}

void CKeyLocker::RunLockNow()
{
	PrintString16(_L("CKeyLocker::RunLockNow"));

	TBool locked = iLocker.IsKeyLockEnabled();
	if( locked )  // if keypad is locked already, set timer and return
	{
		PrintString16(_L("Keypad locked already"));
	}
	else  // keypad is not locked yet
	{
		PrintString16(_L("Lock !!"));
		
		// Using the following line to enable notification or not
		iLocker.EnableSoftNotifications(ETrue);
		if(iEnableNote)
			iLocker.EnableKeyLock();
		else
			iLocker.EnableWithoutNote();
	} // locked

}

TBool CKeyLocker::IsKeyLocked(void)
{
	return iLocker.IsKeyLockEnabled();
}

TBool CKeyLocker::IsCallActive(void)
{
	/* all possible values for iAgent.GetState(KUidCurrentCall)
	ESACallNone;	ESACallVoice;	ESACallFax;	ESACallData;	ESACallAlerting;
	ESACallRinging;	ESACallAlternating;
	*/
	TInt status = iAgent.GetState(KUidCurrentCall);
	if( status == ESACallVoice || status == ESACallRinging )  // there is call or ring
		return ETrue;
	else
		return EFalse;
}
